home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / share / hplip / ui4 / systemtray.pyc (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2009-04-20  |  18.1 KB  |  499 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.6)
  3.  
  4. import sys
  5. import struct
  6. import select
  7. import os
  8. import signal
  9. import os.path as os
  10. import time
  11. from base.g import *
  12. from base import device, utils, models
  13. from base.codes import *
  14. from ui_utils import *
  15.  
  16. try:
  17.     from PyQt4.QtCore import *
  18.     from PyQt4.QtGui import *
  19. except ImportError:
  20.     log.error('Python bindings for Qt4 not found. Try using --qt3. Exiting!')
  21.     sys.exit(1)
  22.  
  23. from systrayframe import SystrayFrame
  24.  
  25. try:
  26.     import dbus
  27.     from dbus import SessionBus, lowlevel
  28. except ImportError:
  29.     log.error('Python bindings for dbus not found. Exiting!')
  30.     sys.exit(1)
  31.  
  32. TRAY_MESSAGE_DELAY = 10000
  33. HIDE_INACTIVE_DELAY = 5000
  34. BLIP_DELAY = 2000
  35. SET_MENU_DELAY = 1000
  36. MAX_MENU_EVENTS = 10
  37. ERROR_STATE_TO_ICON = {
  38.     ERROR_STATE_CLEAR: QSystemTrayIcon.Information,
  39.     ERROR_STATE_OK: QSystemTrayIcon.Information,
  40.     ERROR_STATE_WARNING: QSystemTrayIcon.Warning,
  41.     ERROR_STATE_ERROR: QSystemTrayIcon.Critical,
  42.     ERROR_STATE_LOW_SUPPLIES: QSystemTrayIcon.Warning,
  43.     ERROR_STATE_BUSY: QSystemTrayIcon.Warning,
  44.     ERROR_STATE_LOW_PAPER: QSystemTrayIcon.Warning,
  45.     ERROR_STATE_PRINTING: QSystemTrayIcon.Information,
  46.     ERROR_STATE_SCANNING: QSystemTrayIcon.Information,
  47.     ERROR_STATE_PHOTOCARD: QSystemTrayIcon.Information,
  48.     ERROR_STATE_FAXING: QSystemTrayIcon.Information,
  49.     ERROR_STATE_COPYING: QSystemTrayIcon.Information }
  50. devices = { }
  51.  
  52. class DeviceMenu(QMenu):
  53.     
  54.     def __init__(self, title, parent, device_uri, device_hist, index):
  55.         QMenu.__init__(self, title, parent)
  56.         self.device_uri = device_uri
  57.         self.device_hist = device_hist
  58.         self.index = index
  59.  
  60.     
  61.     def update(self):
  62.         self.clear()
  63.         if self.device_hist:
  64.             first = True
  65.             for e in self.device_hist:
  66.                 error_state = STATUS_TO_ERROR_STATE_MAP.get(e.event_code, ERROR_STATE_CLEAR)
  67.                 ess = device.queryString(e.event_code, 0)
  68.                 a = QAction(QIcon(getStatusListIcon(error_state)[self.index]), QString('%1 %2').arg(ess).arg(getTimeDeltaDesc(e.timedate)), self)
  69.                 if first:
  70.                     f = a.font()
  71.                     f.setBold(True)
  72.                     a.setFont(f)
  73.                     self.setIcon(QIcon(getStatusListIcon(error_state)[self.index]))
  74.                     first = False
  75.                 
  76.                 self.addAction(a)
  77.             
  78.         else:
  79.             self.addAction(QIcon(load_pixmap('warning', '16x16')), QApplication.translate('SystemTray', '(No events)', None, QApplication.UnicodeUTF8))
  80.  
  81.  
  82.  
  83. class HistoryDevice(QObject):
  84.     
  85.     def __init__(self, device_uri, needs_update = True):
  86.         self.needs_update = needs_update
  87.         self.device_uri = device_uri
  88.         (back_end, is_hp, bus, model, serial, dev_file, host, port) = device.parseDeviceURI(device_uri)
  89.         if bus == 'usb':
  90.             self.id = serial
  91.         elif bus == 'net':
  92.             self.id = host
  93.         elif bus == 'par':
  94.             self.id = dev_file
  95.         else:
  96.             self.id = 'unknown'
  97.         self.model = models.normalizeModelUIName(model)
  98.         if back_end == 'hp':
  99.             self.device_type = DEVICE_TYPE_PRINTER
  100.             self.menu_text = self._HistoryDevice__tr('%1 Printer (%2)').arg(self.model).arg(self.id)
  101.         elif back_end == 'hpaio':
  102.             self.device_type = DEVICE_TYPE_SCANNER
  103.             self.menu_text = self._HistoryDevice__tr('%1 Scanner (%2)').arg(self.model).arg(self.id)
  104.         elif back_end == 'hpfax':
  105.             self.device_type = DEVICE_TYPE_FAX
  106.             self.menu_text = self._HistoryDevice__tr('%1 Fax (%2)').arg(self.model).arg(self.id)
  107.         else:
  108.             self.device_type = DEVICE_TYPE_UNKNOWN
  109.             self.menu_text = self._HistoryDevice__tr('%1 (%2)').arg(self.model).arg(self.id)
  110.         self.mq = device.queryModelByURI(self.device_uri)
  111.         self.index = 0
  112.         if self.mq.get('tech-type', TECH_TYPE_NONE) in (TECH_TYPE_MONO_LASER, TECH_TYPE_COLOR_LASER):
  113.             self.index = 1
  114.         
  115.         self.history = None
  116.  
  117.     
  118.     def getHistory(self, service):
  119.         pass
  120.  
  121.     
  122.     def __tr(self, s, c = None):
  123.         return QApplication.translate('SystemTray', s, c, QApplication.UnicodeUTF8)
  124.  
  125.  
  126.  
  127. class SystraySettingsDialog(QDialog):
  128.     
  129.     def __init__(self, parent, systray_visible, polling, polling_interval, device_list = None):
  130.         QDialog.__init__(self, parent)
  131.         self.systray_visible = systray_visible
  132.         if device_list is not None:
  133.             self.device_list = device_list
  134.         else:
  135.             self.device_list = { }
  136.         self.polling = polling
  137.         self.polling_interval = polling_interval
  138.         self.initUi()
  139.         self.SystemTraySettings.updateUi()
  140.  
  141.     
  142.     def initUi(self):
  143.         self.setObjectName('SystraySettingsDialog')
  144.         self.resize(QSize(QRect(0, 0, 488, 565).size()).expandedTo(self.minimumSizeHint()))
  145.         self.gridlayout = QGridLayout(self)
  146.         self.gridlayout.setObjectName('gridlayout')
  147.         self.SystemTraySettings = SystrayFrame(self)
  148.         self.SystemTraySettings.initUi(self.systray_visible, self.polling, self.polling_interval, self.device_list)
  149.         sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
  150.         sizePolicy.setHorizontalStretch(0)
  151.         sizePolicy.setVerticalStretch(0)
  152.         sizePolicy.setHeightForWidth(self.SystemTraySettings.sizePolicy().hasHeightForWidth())
  153.         self.SystemTraySettings.setSizePolicy(sizePolicy)
  154.         self.SystemTraySettings.setFrameShadow(QFrame.Raised)
  155.         self.SystemTraySettings.setObjectName('SystemTraySettings')
  156.         self.gridlayout.addWidget(self.SystemTraySettings, 0, 0, 1, 2)
  157.         spacerItem = QSpacerItem(301, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
  158.         self.gridlayout.addItem(spacerItem, 1, 0, 1, 1)
  159.         self.StdButtons = QDialogButtonBox(self)
  160.         self.StdButtons.setStandardButtons(QDialogButtonBox.Cancel | QDialogButtonBox.NoButton | QDialogButtonBox.Ok)
  161.         self.StdButtons.setCenterButtons(False)
  162.         self.StdButtons.setObjectName('StdButtons')
  163.         self.gridlayout.addWidget(self.StdButtons, 1, 1, 1, 1)
  164.         QObject.connect(self.StdButtons, SIGNAL('accepted()'), self.acceptClicked)
  165.         QObject.connect(self.StdButtons, SIGNAL('rejected()'), self.reject)
  166.         self.setWindowTitle(self._SystraySettingsDialog__tr('HP Device Manager - System Tray Settings'))
  167.  
  168.     
  169.     def acceptClicked(self):
  170.         self.systray_visible = self.SystemTraySettings.systray_visible
  171.         self.polling = self.SystemTraySettings.polling
  172.         self.polling_interval = self.SystemTraySettings.polling_interval
  173.         self.device_list = self.SystemTraySettings.device_list
  174.         self.accept()
  175.  
  176.     
  177.     def __tr(self, s, c = None):
  178.         return QApplication.translate('SystraySettingsDialog', s, c, QApplication.UnicodeUTF8)
  179.  
  180.  
  181.  
  182. class SystemTrayApp(QApplication):
  183.     
  184.     def __init__(self, args, read_pipe):
  185.         QApplication.__init__(self, args)
  186.         self.menu = None
  187.         self.read_pipe = read_pipe
  188.         self.fmt = '64s64sI32sI64sf'
  189.         self.fmt_size = struct.calcsize(self.fmt)
  190.         self.timer_active = False
  191.         self.active_icon = False
  192.         self.user_settings = UserSettings()
  193.         self.user_settings.load()
  194.         self.tray_icon = QSystemTrayIcon()
  195.         pm = load_pixmap('prog', '48x48')
  196.         self.prop_icon = QIcon(pm)
  197.         a = load_pixmap('active', '16x16')
  198.         painter = QPainter(pm)
  199.         painter.drawPixmap(32, 0, a)
  200.         painter.end()
  201.         self.prop_active_icon = QIcon(pm)
  202.         self.tray_icon.setIcon(self.prop_icon)
  203.         self.session_bus = SessionBus()
  204.         self.service = None
  205.         for d in device.getSupportedCUPSDevices(back_end_filter = [
  206.             'hp',
  207.             'hpfax']):
  208.             self.addDevice(d)
  209.         
  210.         self.tray_icon.setToolTip(self._SystemTrayApp__tr('HPLIP Status Service'))
  211.         QObject.connect(self.tray_icon, SIGNAL('messageClicked()'), self.messageClicked)
  212.         notifier = QSocketNotifier(self.read_pipe, QSocketNotifier.Read)
  213.         QObject.connect(notifier, SIGNAL('activated(int)'), self.notifierActivated)
  214.         QObject.connect(self.tray_icon, SIGNAL('activated(QSystemTrayIcon::ActivationReason)'), self.trayActivated)
  215.         self.tray_icon.show()
  216.         if self.user_settings.systray_visible == SYSTRAY_VISIBLE_SHOW_ALWAYS:
  217.             self.tray_icon.setVisible(True)
  218.         else:
  219.             QTimer.singleShot(HIDE_INACTIVE_DELAY, self.timeoutHideWhenInactive)
  220.         self.tray_icon.setIcon(self.prop_active_icon)
  221.         self.active_icon = True
  222.         QTimer.singleShot(SET_MENU_DELAY, self.initDone)
  223.  
  224.     
  225.     def initDone(self):
  226.         self.tray_icon.setIcon(self.prop_icon)
  227.         self.active_icon = False
  228.         self.setMenu()
  229.  
  230.     
  231.     def addDevice(self, device_uri):
  232.         
  233.         try:
  234.             devices[device_uri]
  235.         except KeyError:
  236.             devices[device_uri] = HistoryDevice(device_uri)
  237.  
  238.         devices[device_uri].needs_update = True
  239.  
  240.     
  241.     def setMenu(self):
  242.         self.menu = QMenu()
  243.         title = QWidgetAction(self.menu)
  244.         hbox = QFrame(self.menu)
  245.         layout = QHBoxLayout(hbox)
  246.         layout.setMargin(3)
  247.         layout.setSpacing(5)
  248.         pix_label = QLabel(hbox)
  249.         layout.insertWidget(-1, pix_label, 0)
  250.         icon_size = self.menu.style().pixelMetric(QStyle.PM_SmallIconSize)
  251.         pix_label.setPixmap(self.prop_icon.pixmap(icon_size))
  252.         label = QLabel(hbox)
  253.         layout.insertWidget(-1, label, 20)
  254.         title.setDefaultWidget(hbox)
  255.         label.setText(self._SystemTrayApp__tr('HPLIP Status Service'))
  256.         f = label.font()
  257.         f.setBold(True)
  258.         label.setFont(f)
  259.         self.menu.insertAction(None, title)
  260.         if devices:
  261.             if self.service is None:
  262.                 t = 0
  263.                 while t < 3:
  264.                     
  265.                     try:
  266.                         self.service = self.session_bus.get_object('com.hplip.StatusService', '/com/hplip/StatusService')
  267.                     except DBusException:
  268.                         log.warn('Unable to connect to StatusService. Retrying...')
  269.  
  270.                     t += 1
  271.                     time.sleep(0.5)
  272.             
  273.             if self.service is not None:
  274.                 self.menu.addSeparator()
  275.                 for d in devices:
  276.                     devices[d].getHistory(self.service)
  277.                     menu = DeviceMenu(devices[d].menu_text, self.menu, d, devices[d].history, devices[d].index)
  278.                     self.menu.addMenu(menu)
  279.                     menu.update()
  280.                 
  281.             
  282.         
  283.         self.menu.addSeparator()
  284.         self.menu.addAction(self._SystemTrayApp__tr('HP Device Manager...'), self.toolboxTriggered)
  285.         self.menu.addSeparator()
  286.         self.settings_action = self.menu.addAction(QIcon(load_pixmap('settings', '16x16')), self._SystemTrayApp__tr('Settings...'), self.settingsTriggered)
  287.         self.menu.addSeparator()
  288.         self.menu.addAction(QIcon(load_pixmap('quit', '16x16')), 'Quit', self.quitTriggered)
  289.         self.tray_icon.setContextMenu(self.menu)
  290.  
  291.     
  292.     def settingsTriggered(self):
  293.         if self.menu is None:
  294.             return None
  295.         self.sendMessage('', '', EVENT_DEVICE_STOP_POLLING)
  296.         
  297.         try:
  298.             dlg = SystraySettingsDialog(self.menu, self.user_settings.systray_visible, self.user_settings.polling, self.user_settings.polling_interval, self.user_settings.polling_device_list)
  299.             if dlg.exec_() == QDialog.Accepted:
  300.                 self.user_settings.systray_visible = dlg.systray_visible
  301.                 self.user_settings.save()
  302.                 if self.user_settings.systray_visible == SYSTRAY_VISIBLE_SHOW_ALWAYS:
  303.                     log.debug('Showing...')
  304.                     self.tray_icon.setVisible(True)
  305.                 else:
  306.                     log.debug('Waiting to hide...')
  307.                     QTimer.singleShot(HIDE_INACTIVE_DELAY, self.timeoutHideWhenInactive)
  308.                 self.sendMessage('', '', EVENT_USER_CONFIGURATION_CHANGED)
  309.         finally:
  310.             self.sendMessage('', '', EVENT_DEVICE_START_POLLING)
  311.  
  312.  
  313.     
  314.     def timeoutHideWhenInactive(self):
  315.         log.debug('Hiding...')
  316.         if self.user_settings.systray_visible in (SYSTRAY_VISIBLE_HIDE_WHEN_INACTIVE, SYSTRAY_VISIBLE_HIDE_ALWAYS):
  317.             self.tray_icon.setVisible(False)
  318.             log.debug('Hidden')
  319.         
  320.  
  321.     
  322.     def updateMenu(self):
  323.         if self.menu is None:
  324.             return None
  325.         for a in self.menu.actions():
  326.             
  327.             try:
  328.                 a.menu().update()
  329.             continue
  330.             except AttributeError:
  331.                 self.menu is None
  332.                 self.menu is None
  333.                 continue
  334.                 continue
  335.             
  336.  
  337.         
  338.  
  339.     
  340.     def trayActivated(self, reason):
  341.         if reason == QSystemTrayIcon.Context:
  342.             self.updateMenu()
  343.         elif reason == QSystemTrayIcon.DoubleClick:
  344.             self.toolboxTriggered()
  345.         elif reason == QSystemTrayIcon.Trigger:
  346.             pass
  347.         elif reason == QSystemTrayIcon.MiddleClick:
  348.             pass
  349.         
  350.  
  351.     
  352.     def messageClicked(self):
  353.         pass
  354.  
  355.     
  356.     def quitTriggered(self):
  357.         log.debug('Exiting')
  358.         self.sendMessage('', '', EVENT_SYSTEMTRAY_EXIT)
  359.         self.quit()
  360.  
  361.     
  362.     def toolboxTriggered(self):
  363.         
  364.         try:
  365.             os.waitpid(-1, os.WNOHANG)
  366.         except OSError:
  367.             pass
  368.  
  369.         (ok, lock_file) = utils.lock_app('hp-toolbox', True)
  370.         if ok:
  371.             utils.unlock(lock_file)
  372.             path = utils.which('hp-toolbox')
  373.             if path:
  374.                 path = os.path.join(path, 'hp-toolbox')
  375.             else:
  376.                 self.tray_icon.showMessage(self._SystemTrayApp__tr('HPLIP Status Service'), self._SystemTrayApp__tr('Unable to locate hp-toolbox on system PATH.'), QSystemTrayIcon.Critical, TRAY_MESSAGE_DELAY)
  377.                 log.error('Unable to find hp-toolbox on PATH.')
  378.                 return None
  379.             path.debug('Running hp-toolbox: hp-toolbox')
  380.             os.spawnlp(os.P_NOWAIT, path, 'hp-toolbox')
  381.         else:
  382.             self.sendMessage('', '', EVENT_RAISE_DEVICE_MANAGER, interface = 'com.hplip.Toolbox')
  383.  
  384.     
  385.     def sendMessage(self, device_uri, printer_name, event_code, username = prop.username, job_id = 0, title = '', pipe_name = '', interface = 'com.hplip.StatusService'):
  386.         device.Event(device_uri, printer_name, event_code, username, job_id, title).send_via_dbus(self.session_bus, interface)
  387.  
  388.     
  389.     def notifierActivated(self, s):
  390.         m = ''
  391.         while True:
  392.             
  393.             try:
  394.                 (r, w, e) = select.select([
  395.                     self.read_pipe], [], [
  396.                     self.read_pipe], 1)
  397.             except select.error:
  398.                 log.debug('Error in select()')
  399.                 break
  400.  
  401.             if e:
  402.                 log.error('Pipe error: %s' % e)
  403.                 break
  404.             
  405.             if r:
  406.                 m = ''.join([
  407.                     m,
  408.                     os.read(self.read_pipe, self.fmt_size)])
  409.                 while len(m) >= self.fmt_size:
  410.                     event = device.Event(*struct.unpack(self.fmt, m[:self.fmt_size]))
  411.                     m = m[self.fmt_size:]
  412.                     if event.event_code == EVENT_USER_CONFIGURATION_CHANGED:
  413.                         log.debug('Re-reading configuration (EVENT_USER_CONFIGURATION_CHANGED)')
  414.                         self.user_settings.load()
  415.                         self.user_settings.debug()
  416.                     elif event.event_code == EVENT_SYSTEMTRAY_EXIT:
  417.                         self.quit()
  418.                         return None
  419.                     if self.user_settings.systray_visible in (SYSTRAY_VISIBLE_SHOW_ALWAYS, SYSTRAY_VISIBLE_HIDE_WHEN_INACTIVE):
  420.                         log.debug('Showing...')
  421.                         self.tray_icon.setVisible(True)
  422.                         if event.event_code == EVENT_DEVICE_UPDATE_ACTIVE:
  423.                             if not self.active_icon:
  424.                                 self.tray_icon.setIcon(self.prop_active_icon)
  425.                                 self.active_icon = True
  426.                                 continue
  427.                             continue
  428.                         elif event.event_code == EVENT_DEVICE_UPDATE_INACTIVE:
  429.                             if self.active_icon:
  430.                                 self.tray_icon.setIcon(self.prop_icon)
  431.                                 self.active_icon = False
  432.                                 continue
  433.                             continue
  434.                         elif event.event_code == EVENT_DEVICE_UPDATE_BLIP:
  435.                             if not self.active_icon:
  436.                                 self.tray_icon.setIcon(self.prop_active_icon)
  437.                                 self.active_icon = True
  438.                                 QTimer.singleShot(BLIP_DELAY, self.blipTimeout)
  439.                                 continue
  440.                             continue
  441.                         
  442.                     
  443.                     if self.user_settings.systray_visible in (SYSTRAY_VISIBLE_HIDE_WHEN_INACTIVE, SYSTRAY_VISIBLE_HIDE_ALWAYS):
  444.                         log.debug('Waiting to hide...')
  445.                         QTimer.singleShot(HIDE_INACTIVE_DELAY, self.timeoutHideWhenInactive)
  446.                     
  447.                     if event.event_code <= EVENT_MAX_USER_EVENT:
  448.                         self.addDevice(event.device_uri)
  449.                         self.setMenu()
  450.                         if self.tray_icon.supportsMessages():
  451.                             log.debug('Tray icon message:')
  452.                             event.debug()
  453.                             error_state = STATUS_TO_ERROR_STATE_MAP.get(event.event_code, ERROR_STATE_CLEAR)
  454.                             icon = ERROR_STATE_TO_ICON.get(error_state, QSystemTrayIcon.Information)
  455.                             desc = device.queryString(event.event_code)
  456.                             if event.job_id and event.title:
  457.                                 log.debug('Bubble: uri=%s desc=%s title=%s user=%s job_id=%d code=%d' % (event.device_uri, desc, event.title, event.username, event.job_id, event.event_code))
  458.                                 self.tray_icon.showMessage(self._SystemTrayApp__tr('HPLIP Device Status'), QString('%1\n%2: %3\n(%4/%5)').arg(event.device_uri).arg(desc).arg(event.title).arg(event.username).arg(event.job_id), icon, TRAY_MESSAGE_DELAY)
  459.                             else:
  460.                                 log.debug('Bubble: uri=%s desc=%s code=%d' % (event.device_uri, desc, event.event_code))
  461.                                 self.tray_icon.showMessage(self._SystemTrayApp__tr('HPLIP Device Status'), QString('%1\n%2 (%3)').arg(event.device_uri).arg(desc).arg(event.event_code), icon, TRAY_MESSAGE_DELAY)
  462.                         
  463.                     self.tray_icon.supportsMessages()
  464.                 continue
  465.             break
  466.  
  467.     
  468.     def blipTimeout(self):
  469.         if self.active_icon:
  470.             self.tray_icon.setIcon(self.prop_icon)
  471.             self.active_icon = False
  472.         
  473.  
  474.     
  475.     def __tr(self, s, c = None):
  476.         return QApplication.translate('SystemTray', s, c, QApplication.UnicodeUTF8)
  477.  
  478.  
  479.  
  480. def run(read_pipe):
  481.     log.set_module('hp-systray(qt4)')
  482.     log.debug('PID=%d' % os.getpid())
  483.     app = SystemTrayApp(sys.argv, read_pipe)
  484.     app.setQuitOnLastWindowClosed(False)
  485.     i = 0
  486.     while i < 10:
  487.         if QSystemTrayIcon.isSystemTrayAvailable():
  488.             break
  489.         
  490.         time.sleep(1)
  491.         i += 1
  492.     if not QSystemTrayIcon.isSystemTrayAvailable():
  493.         FailureUI(None, QApplication.translate('SystemTray', '<b>No system tray detected on this system.</b><p>Unable to start, exiting.</p>', None, QApplication.UnicodeUTF8), QApplication.translate('SystemTray', 'HPLIP Status Service', None, QApplication.UnicodeUTF8))
  494.     else:
  495.         notifier = QSocketNotifier(read_pipe, QSocketNotifier.Read)
  496.         QObject.connect(notifier, SIGNAL('activated(int)'), app.notifierActivated)
  497.         app.exec_()
  498.  
  499.